/**
 * @file midi2_translator.c
 * @brief MIDI 1.0 ↔ MIDI 2.0 格式转换器实现
 * @details 实现MIDI消息格式之间的转换逻辑
 * @version 1.0
 * @date 2025-11-04
 */

#include "midi2_translator.h"
#include "midi_protocol.h"
#include "board.h"
#include <string.h>

/* ============================================================================
 * 公共函数实现
 * ============================================================================ */

/**
 * @brief 将MIDI 2.0消息转换为MIDI 1.0格式
 */
int midi2_to_midi1(midi2_message_t *msg2, midi_message_t *msg1)
{
    /* 参数检查 */
    if (msg2 == NULL || msg1 == NULL)
    {
        return -1;
    }

    /* 清零输出结构体 */
    memset(msg1, 0, sizeof(midi_message_t));

    /* 提取基本信息 */
    msg1->channel = msg2->channel;
    uint8_t status_type = msg2->status & 0xF0;

    /* 根据状态类型转换 */
    switch (status_type)
    {
        case 0x80:  /* Note Off */
            msg1->type = MIDI_MSG_NOTE_OFF;
            msg1->note = msg2->note;
#if MIDI2_INTERNAL_16BIT_VEL
            /* 保留 16 位精度 */
            msg1->velocity_16 = msg2->velocity_16;
#else
            /* 转换为 7 位精度 */
            msg1->velocity = MIDI2_VEL_16TO7(msg2->velocity_16);
#endif
            break;

        case 0x90:  /* Note On */
#if MIDI2_INTERNAL_16BIT_VEL
            /* 保留 16 位精度 */
            msg1->velocity_16 = msg2->velocity_16;
            if (msg1->velocity_16 == 0)
            {
                msg1->type = MIDI_MSG_NOTE_OFF;
            }
            else
            {
                msg1->type = MIDI_MSG_NOTE_ON;
            }
#else
            /* 转换为 7 位精度 */
            msg1->velocity = MIDI2_VEL_16TO7(msg2->velocity_16);
            if (msg1->velocity == 0)
            {
                msg1->type = MIDI_MSG_NOTE_OFF;
            }
            else
            {
                msg1->type = MIDI_MSG_NOTE_ON;
            }
#endif
            msg1->note = msg2->note;
            break;

        case 0xB0:  /* Control Change */
            msg1->type = MIDI_MSG_CONTROL_CHANGE;
            msg1->controller = msg2->note;  /* MIDI 2.0中controller number存储在note字段 */
            msg1->value = MIDI2_CC_32TO7(msg2->controller_32);

            /* 检查特殊控制器 */
            if (msg1->controller == 0x7B && msg1->value == 0x00)
            {
                msg1->type = MIDI_MSG_ALL_NOTES_OFF;
            }
            else if (msg1->controller == 0x0E)
            {
                msg1->type = MIDI_MSG_SETUP_MODE;
            }
            else if (msg1->controller == 0x0F && msg1->value == 0x7F)
            {
                msg1->type = MIDI_MSG_TEMP_WARNING;
            }
            break;

        case 0xA0:  /* Polyphonic Pressure */
        case 0xC0:  /* Program Change */
        case 0xD0:  /* Channel Pressure */
        case 0xE0:  /* Pitch Bend */
            /* 这些消息类型暂不处理，返回UNKNOWN */
            msg1->type = MIDI_MSG_UNKNOWN;
            break;

        default:
            return -1;  /* 未知状态类型 */
    }

    return 0;
}

/**
 * @brief 将MIDI 1.0消息转换为MIDI 2.0格式
 */
int midi1_to_midi2(midi_message_t *msg1, midi2_message_t *msg2)
{
    /* 参数检查 */
    if (msg1 == NULL || msg2 == NULL)
    {
        return -1;
    }

    /* 清零输出结构体 */
    memset(msg2, 0, sizeof(midi2_message_t));

    /* 设置默认值 */
    msg2->mt = UMP_MT_MIDI2_CHANNEL;  /* 默认使用MT4 (MIDI 2.0) */
    msg2->group = 0;                  /* 默认Group 0 */
    msg2->channel = msg1->channel;
    msg2->attr_type = ATTR_NONE;      /* 无属性 */

    /* 根据消息类型转换 */
    switch (msg1->type)
    {
        case MIDI_MSG_NOTE_ON:
            msg2->status = 0x90 | msg2->channel;
            msg2->note = msg1->note;
            msg2->velocity_16 = MIDI2_VEL_7TO16(msg1->velocity);
            break;

        case MIDI_MSG_NOTE_OFF:
            msg2->status = 0x80 | msg2->channel;
            msg2->note = msg1->note;
            msg2->velocity_16 = MIDI2_VEL_7TO16(msg1->velocity);
            break;

        case MIDI_MSG_CONTROL_CHANGE:
        case MIDI_MSG_ALL_NOTES_OFF:
        case MIDI_MSG_SETUP_MODE:
        case MIDI_MSG_TEMP_WARNING:
            msg2->status = 0xB0 | msg2->channel;
            msg2->note = msg1->controller;  /* Controller number存储在note字段 */
            msg2->controller_32 = MIDI2_CC_7TO32(msg1->value);
            break;

        case MIDI_MSG_UNKNOWN:
        default:
            return -1;  /* 无法转换的消息类型 */
    }

    return 0;
}
